#pragma once

#include <iostream>
#include <functional>
#include <vector>
#include <unistd.h>

#include "Sock.hpp"
#include "serialization.hpp"

using func_t = std::function<void(int)>;

class TcpServer
{
public:
    TcpServer(uint16_t port, const std::string &ip = "")
        : _sockfd(-1), _ip(ip), _port(port)
    {
    }

    ~TcpServer()
    {
        close(_sockfd);
        close(_serversockfd);
    }

    void InitServer()
    {
        Sock sock;
        _sockfd = sock.Socket();
        sock.Bind(_sockfd, _ip, _port);
        sock.Listen(_sockfd);
    }

    void BindServer(const func_t& fun)
    {
        _funcs.push_back(fun);
    }

    void RunServer(int num)
    {
        for (auto &fun : _funcs)
        {
            fun(num);
        }
    }

    void StartServer()
    {
        while (true)
        {
            Sock sock;
            std::string clientip;
            uint16_t clientport;
            _serversockfd = sock.Accept(_sockfd, &clientip, &clientport);
            if (_serversockfd < 0)
                continue;

            RunServer(_serversockfd);
        }
    }

public:
    int _sockfd;
    int _serversockfd;
    std::string _ip;
    uint16_t _port;
    std::vector<func_t> _funcs;
};